home *** CD-ROM | disk | FTP | other *** search
/ Turnbull China Bikeride / Turnbull China Bikeride - Disc 2.iso / BARNET / COMPILER / SATHER / !Sather / Library / Containrs / sa / h_bag < prev    next >
Text File  |  1996-04-09  |  5KB  |  188 lines

  1. ---------------------------> Sather 1.1 source file <--------------------------
  2. -- h_bag.sa: Hash table based bag
  3. -- Author: Benedict A. Gomes <gomes@samosa.ICSI.Berkeley.EDU>
  4. -- Copyright (C) 1995, International Computer Science Institute
  5. -- $Id: h_bag.sa,v 1.5 1996/04/09 10:05:03 borisv Exp $
  6. --
  7. -- COPYRIGHT NOTICE: This code is provided WITHOUT ANY WARRANTY
  8. -- and is subject to the terms of the SATHER LIBRARY GENERAL PUBLIC
  9. -- LICENSE contained in the file: Sather/Doc/License of the
  10. -- Sather distribution. The license is also available from ICSI,
  11. -- 1947 Center St., Suite 600, Berkeley CA 94704, USA.
  12. -------------------------------------------------------------------
  13. class BAG{E} < $BAG{E} is 
  14.    -- A standard bag is an alias for an H_BAG{E}. See the ancestors
  15.    -- 
  16.    -- Usage:
  17.    --   b ::= #BAG{INT}(|10,10,11|);
  18.    --   a: INT := 0;
  19.    --   loop a := a+b.elt!; end;     -- adds the bag elemetns in some 
  20.    --                                -- undefined order. 
  21.    --   
  22.  
  23.    include H_BAG{E} 
  24. end;
  25. --==========================================================================
  26. class H_BAG{E} < $BAG{E} is
  27.    -- This Bag sorts its elements by counting the number of occurences.
  28.    -- If two _different but equal_ elements are inserted only one of
  29.    -- them will be stored, but this one will be yielded twice.
  30.    -- 
  31.    private include DYNAMIC_DATABUCKET_TABLE{E,INT}
  32.      create->private old_create, 
  33.      map_aget->private aget,map_aset->private aset,
  34.      map_key!->unique!;    -- Make the key routine public
  35.    include BAG_INCL{E};
  36.  
  37.    private attr total_size: INT;
  38.    
  39.    --              ------ Initialization/Duplication ------
  40.    private internal_create: SAME is
  41.       -- Redefine the stub routine in "BAG_INCL"
  42.       return create;
  43.    end;
  44.    
  45.    create: SAME is
  46.       return old_create
  47.    end;
  48.  
  49.    create(e: $ELT{E}): SAME is
  50.       res: SAME := #;
  51.       loop res.insert(e.elt!) end;
  52.       return res;
  53.    end;
  54.  
  55.    create_from(a: ARRAY{E}): SAME is
  56.       -- Create a bag from the elements of array "a".
  57.       return #SAME(a);
  58.    end;
  59.    
  60.    copy: SAME  pre ~void(self) is
  61.       res ::= map_copy;
  62.       res.total_size := total_size;
  63.       return res
  64.    end;
  65.  
  66.    -- ------------------- Access  -------------------------
  67.    n_unique: INT is return n_inds end;
  68.    -- Return the number of unique indicies
  69.    
  70.    count(e:E): INT  pre ~void(self) is
  71.       -- Return the number of occurences of element "e"
  72.       loop
  73.      b ::= bucket(hash(e)).list!;
  74.      if elt_eq(b.item,e) then return b.data end
  75.       end;
  76.       return 0
  77.    end;
  78.  
  79.    has(e:E): BOOL pre ~void(self) is
  80.       return count(e) > 0
  81.    end;
  82.  
  83.    insert(e:E)  pre ~void(self) is
  84.       h ::= hash(e);
  85.       loop
  86.      b ::= bucket(h).list!;
  87.      if elt_eq(e,b.item) then
  88.         b.data := b.data + 1;
  89.         total_size := total_size + 1;
  90.         return
  91.      end
  92.       end;
  93.       set_bucket(h,#DATABUCKET{E,INT}(e,1,bucket(h)));
  94.       -- TODO: optimize the bucket(h)
  95.  
  96.       total_size := total_size + 1;
  97.       n_inds := n_inds + 1;
  98.       update_insert
  99.    end;
  100.  
  101.    delete(e:E) pre ~void(self) is
  102.       dummy ::= delete(e)
  103.    end;
  104.  
  105.    delete(e:E): E   pre ~void(self) is
  106.       h ::= hash(e);
  107.       b ::= bucket(h);
  108.       prev ::= b; prev := void;    -- NASTY HACK
  109.       if void(b) then return void end;
  110.       loop until!( void(b) );
  111.      res ::= b.item;
  112.      if elt_eq(res,e) then
  113.         total_size := total_size - 1;
  114.         if b.data = 1 then
  115.            -- last occurrence removed
  116.            if void(prev) then
  117.           set_bucket(h,b.next)
  118.            else
  119.           prev.next(b.next)
  120.            end;
  121.            n_inds := n_inds - 1;
  122.            update_delete
  123.         else
  124.            b.data := b.data - 1
  125.         end;
  126.         return res
  127.      end;
  128.      prev := b;
  129.      b := b.next
  130.       end;
  131.       return void
  132.    end;
  133.  
  134.    delete_all(e:E)   
  135.    -- Delete all elements equal to "e"
  136.       pre ~void(self) 
  137.    is      
  138.       dummy ::= delete_all(e)
  139.    end;
  140.  
  141.    delete_all(e:E): INT   pre ~void(self) is
  142.       anz ::= count(e);
  143.       if anz = 0 then return 0 end;
  144.       total_size := total_size - anz;
  145.       return map_delete(e)
  146.    end;
  147.  
  148.    elt!: E  pre ~void(self) is
  149.       loop
  150.      b ::= bucket( 0.upto!(asize-1) );
  151.      loop
  152.         bk ::= b.list!;
  153.         loop bk.data.times!; yield bk.item end
  154.      end
  155.       end
  156.    end;
  157.  
  158.    intersection(a:$RO_BAG{E}): $BAG{E}
  159.    -- The intersection of two bag has the element with the
  160.    -- minimal occurence of both bags.
  161.       pre ~void(self) and ~void(a)
  162.    is
  163.       res ::= create;
  164.       loop
  165.      p ::= map_pair!;
  166.      acount ::= a.count(p.t1);
  167.      min ::= p.t2;
  168.      if acount < min then min := acount end;
  169.      if min > 0 then
  170.         res[p.t1] := min;
  171.         res.total_size := res.total_size + min
  172.      end
  173.       end;
  174.       return res
  175.    end;
  176.  
  177.    difference(a:$RO_BAG{E}): $BAG{E}
  178.    -- Returns a bag which represents the difference between self and "a"
  179.       pre ~void(self) and ~void(a)
  180.    is
  181.       res ::= copy;
  182.       loop res.delete(a.elt!) end;
  183.       return res
  184.    end;
  185.  
  186. end; -- H_BAG{E}
  187. --============================================================================
  188.